package com.dake.jdk8.reflect;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test {

    private final static String PACK_VO_PATH = "com.dake.jdk8.vo.reflect.";
    private final static String PACK_VO_PARAM_PATH = "com.dake.jdk8.vo.reflect.";

    public static void main(String[] args) {

        Test.processString();
    }

    public static void processString() {
        String aa1 = "Aa.aParam1";
        String aa2 = "Aa.Bb[0].Cc[0].dd1";
        String aa3 = "Aa.Bb[0].Cc[0].dd2";
        String aa4 = "Aa.Bb[0].Cc[1].dd1";
        String aa5 = "Aa.Bb[0].Cc[1].dd2";
        String aa6 = "Aa.Bb[1].Cc[1].dd1";
        String aa7 = "Aa.Bb[1].Cc[0].dd1";
        String aa8 = "Aa.Bb[1].name";


        List<String> list = new ArrayList<>();
        list.add(aa6);
        list.add(aa7);
        list.add(aa8);
        list.add(aa1);
        list.add(aa2);
        list.add(aa3);
        list.add(aa4);
        list.add(aa5);

        //1.获取部件类的实体对象

        String className = list.get(0).split("\\.")[0];
        Class clazz1 = null;

        Object lv0Entity = null;
        try {
            clazz1 = Class.forName(PACK_VO_PATH + className);
            lv0Entity = clazz1.newInstance();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        //上层传入下层递归的对象
        Object object = lv0Entity;
        Map<String, Object> map = new HashMap<String, Object>();//全局map，以路径为key，对应的对象为value
        //2.循环数组，解析每条string
        for (String record : list) {
            /**
             * 解析一条String
             */
            //根据"."进行分割，从第二个开始解析数据
            String[] tmpArr = record.split("\\.");
            //递归方法，参数为tmpArr[i]和上层对象
            Test.diGui(object, tmpArr, 1, map, record);


        }
        System.out.println(object);
    }

    public static Object getValue() {
        return "123";
    }

    public static Object diGui(Object preObject, String[] strArr, int index, Map<String, Object> map, String record) {
        try {
            String str = strArr[index];
            //如果不包含"["符号，表示这是一个String属性，创建该属性后传递给下层
            if (!str.contains("[")) {
                Object curObject = new Object();
                if (index + 1 == strArr.length) {
                    //最后一层，直接将值赋给上层对象
                    try {
                        Field f = preObject.getClass().getDeclaredField(str);
                        f.setAccessible(true);
                        f.set(preObject, getValue());
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }

                    return preObject;
                }
            } else {
                //如果包含"["符号，表示这是一个list中的一个对象，先判断该上层对象中是否有该list
                //如果没有则创建list，创建下标对应的对象，调用下层递归赋值，然后塞入list（并将对象塞入全局Map中）
                //如果有list，则根据key从全局Map中尝试获取该对象，如果获取不到则新建对象，调用下层递归赋值，然后塞入list（并将对象塞入全局Map中）

                String listName = str.substring(0, str.indexOf("[")).toLowerCase() + "List";//list名称
                //String listIndex=str.substring(str.indexOf("[")+1,str.indexOf("]"));//当前需要解析的下标
                String paramClassName = str.substring(0, str.indexOf("["));//当前需要解析的class名称（不包括路径）
                //全局map，以路径为key，对应的对象为value;比如当前解析到Aa.Bb[0].Cc[0]这一层，则可以"Aa.Bb[0].Cc[0]"为key，尝试获取ccList中逻辑下标为0的对象cc
                String key = "";
                for (int i = 0; i <= index; i++) {
                    key = key + strArr[i] + ".";
                }
                key = key.substring(0, key.length() - 1);
                Object curObject = map.get(key);
                if (null == curObject) {
                    Class clazz1 = Class.forName(PACK_VO_PARAM_PATH + paramClassName);
                    curObject = clazz1.newInstance();
                }
                Class preClazz = preObject.getClass();
                Field[] fields = preClazz.getDeclaredFields();
                for (Field field : fields) {
                    String fieldName = field.getName();
                    field.setAccessible(true);
                    if (fieldName.equals(listName)) {
                        List listObj = (List) field.get(preObject);

                        if (null == listObj) {
                            listObj = new ArrayList();
                        }
                        //调用递归设置curObj，然后将curObj设置到list中，再将list设置到上层对象中
                        index++;
                        curObject = Test.diGui(curObject, strArr, index, map, record);
                        if (null == map.get(key)) {
                            map.put(key, curObject);
                            listObj.add(curObject);
                        }
                        PropertyDescriptor pd = new PropertyDescriptor(field.getName(), preClazz);
                        Method wM = pd.getWriteMethod();//获得写方法
                        wM.invoke(preObject, listObj);//因为知道是list类型的属性，所以传个list过去就可以了
                        return preObject;
                    }
                }
            }

        } catch (IllegalAccessException | IntrospectionException | InvocationTargetException | ClassNotFoundException | InstantiationException e) {
            throw new RuntimeException();
        }
        return preObject;
    }
}
